package cn.tedu.knows.sys.service.impl;


import cn.tedu.knows.commons.exception.ServiceException;
import cn.tedu.knows.commons.model.*;
import cn.tedu.knows.sys.mapper.ClassroomMapper;
import cn.tedu.knows.sys.mapper.UserMapper;
import cn.tedu.knows.sys.mapper.UserRoleMapper;
import cn.tedu.knows.sys.service.IUserService;
import cn.tedu.knows.sys.vo.RegisterVo;
import cn.tedu.knows.sys.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tedu.cn
 * @since 2021-07-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    // 接口名上按Ctrl+Alt+B就会自动跳转到唯一实现类

    @Autowired
    private ClassroomMapper classroomMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;

    private PasswordEncoder encoder=
            new BCryptPasswordEncoder();

    //注册学生的实现方法
    @Override
    public void registerStudent(RegisterVo registerVo) {
        //1.验证邀请码正确与否
        QueryWrapper<Classroom> query=new QueryWrapper<>();
        query.eq("invite_code",
                                registerVo.getInviteCode());
        Classroom classroom=classroomMapper.selectOne(query);
        //    如果查询出的班级是null 证明邀请码不正确
        if(classroom==null){
            throw new ServiceException("邀请码错误!");
        }
        //2.验证手机号是否注册过
        User user=userMapper.findUserByUsername(
                                    registerVo.getPhone());
        if(user!=null){
            throw new ServiceException("手机号已经注册过!");
        }
        //3.用户输入的密码进行加密
        String bcrypt="{bcrypt}"+encoder.encode(
                                    registerVo.getPassword());
        //4.构建user对象并赋值
        User u=new User();
        u.setUsername(registerVo.getPhone());
        u.setNickname(registerVo.getNickname());
        u.setPassword(bcrypt);
        u.setClassroomId(classroom.getId());
        u.setCreatetime(LocalDateTime.now());
        u.setEnabled(1);
        u.setLocked(0);
        u.setType(0);
        //5.user新增到数据库
        //  insert方法中除了新增user对象到数据库之外
        //  它还会将数据库表中新增的自增列的值,赋值给当前u对象的id
        int num=userMapper.insert(u);
        if(num!=1){
            throw new ServiceException("数据库异常,注册失败");
        }
        //6.构建用户和角色的关系对象,并新增到关系表中
        UserRole userRole=new UserRole();
        // u对象的id属性是insert方法中自动赋值的!
        userRole.setUserId(u.getId());
        userRole.setRoleId(2);
        num=userRoleMapper.insert(userRole);
        if(num!=1){
            throw new ServiceException("数据库异常,注册失败");
        }
    }

    //利用Timer周期调用方法,每隔30分钟清空一次缓存
    //以保证每30分钟和数据库同步一次
    Timer timer=new Timer();

    //静态块是当前类加载到java虚拟机时运行一次
    //一般情况下,一个类只会加载到JVM一次,所以静态块中的代码也只运行一次

    {
        //这里是普通初始化块,和java虚拟机加载无关
        //只要实例化当前类对象,在运行构造方法之前会先运行这里的代码
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                synchronized (teachers) {
                    synchronized (teacherMap){
                        teachers.clear();
                        teacherMap.clear();
                    }
                }
                System.out.println("缓存已清空");
            }
        },1000*60*30,1000*60*30);
    }


    private List<User> teachers=new CopyOnWriteArrayList<>();
    private Map<String,User> teacherMap=new ConcurrentHashMap<>();
    @Override
    public List<User> getTeachers() {
        if(teachers.isEmpty()) {
            synchronized (teachers) {
                if(teachers.isEmpty()) {
                    QueryWrapper<User> query = new QueryWrapper<>();
                    query.eq("type", 1);
                    List<User> list = userMapper.selectList(query);
                    teachers.addAll(list);
                    for(User u:list){
                        teacherMap.put(u.getNickname(),u);
                    }
                }
            }
        }
        //千万别忘了返回
        return teachers;
    }

    @Override
    public Map<String, User> getTeacherMap() {
        if(teacherMap.isEmpty()){
            getTeachers();
        }
        //千万别忘了返回
        return teacherMap;
    }

    @Autowired
    private RestTemplate restTemplate;
    @Override
    public UserVo getCurrentUserVo(String username) {
        //获得UserVo对象
        UserVo userVo=userMapper.findUserVoByUsername(username);
        // 按查询出的userVo中的id查询这个用户的问题数
        String url=
            "http://faq-service/v2/questions/count?userId={1}";
        Integer num=restTemplate.getForObject(
                url,Integer.class,userVo.getId());
        // 将查询出的问题数赋值为userVo
        userVo.setQuestions(num);
        //作业收藏数: 根据用户id查询出收藏数之后赋值给collections属性
        //默认赋值0
        userVo.setCollections(0);
        //别忘了返回
        return userVo;
    }

    @Override
    public User getUserByUsername(String username) {
        return userMapper.findUserByUsername(username);
    }

    @Override
    public List<Role> getRolesById(Integer id) {
        return userMapper.findUserRolesById(id);
    }

    @Override
    public List<Permission> getPermissionsById(Integer id) {
        return userMapper.findUserPermissionsById(id);
    }
}



